package tcp

import (
	"bufio"
	"context"
	"godis/lib/logger"
	"godis/lib/sync/atomic"
	"godis/lib/sync/wait"
	"io"
	"net"
	"sync"
	"time"
)

type EchoClient struct {
	Conn    net.Conn
	Waiting wait.Wait
}

func MakeHandler() *EchoHandler {
	return &EchoHandler{}
}

func (e *EchoClient) Close() error {
	e.Waiting.WaitWithTimeout(10 * time.Second)
	_ = e.Conn.Close()
	return nil
}

type EchoHandler struct {
	activeConn sync.Map
	closing    atomic.Boolean // 由于多线程并发问题，我们使用自行实现的原子bool

}

func (handler *EchoHandler) Handle(ctx context.Context, conn net.Conn) {
	if handler.closing.Get() {
		_ = conn.Close()
	}
	client := &EchoClient{
		Conn: conn,
	}
	handler.activeConn.Store(client, struct{}{}) // 只存储key即可
	reader := bufio.NewReader(conn)
	for true {
		msg, err := reader.ReadString('\n') // 不断读取用户发送的消息

		if err != nil {
			if err == io.EOF { // 接收到了结束符
				logger.Info("Connection is closed")
				handler.activeConn.Delete(client)
			} else {
				logger.Warn(err)
			}
			return
		}

		client.Waiting.Add(1) // 告诉Client数据结构我们正在做业务，请等待至多10s
		b := []byte(msg)      // 把msg转化成字节
		_, _ = conn.Write(b)  // 向用户回写用户发来的信息
		client.Waiting.Done()
	}
}

func (handler EchoHandler) Close() error {
	logger.Info("handler is shutting down")
	handler.closing.Set(true) // boolean 表示关闭
	// 我们的业务引擎关闭，所以map中的连接全部清除
	handler.activeConn.Range(func(key, value any) bool {
		client := key.(*EchoClient)
		_ = client.Conn.Close()
		return true
	})
	return nil
}
